package sendGoodsRecord

import (
	"context"
	"errors"
	"github.com/google/uuid"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"insighttracking/apps/sorting/auth"
	"insighttracking/common/utils"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"insighttracking/query/service"
	"net/http"

	"insighttracking/apps/sorting/internal/svc"
	"insighttracking/apps/sorting/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
	"os"
)

type CreateOutGoodsRecordApiLogic struct {
	logx.Logger
	ctx     context.Context
	svcCtx  *svc.ServiceContext
	Request *http.Request
}

func NewCreateOutGoodsRecordApiLogic(ctx context.Context, svcCtx *svc.ServiceContext, request *http.Request) *CreateOutGoodsRecordApiLogic {
	hostname, _ := os.Hostname()
	return &CreateOutGoodsRecordApiLogic{
		Logger: logx.WithContext(ctx).WithCallerSkip(0).WithFields(
			logx.Field("Log_UUID", uuid.New().String()),
			logx.Field("hostname", hostname)),
		ctx:     ctx,
		svcCtx:  svcCtx,
		Request: request,
	}
}

// CreateOutGoodsRecordApi 分拣端根据分拣重量来出库
func (l *CreateOutGoodsRecordApiLogic) CreateOutGoodsRecordApi(req *types.CreateOutGoodsRecordReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return "", err
	}
	// 判断当前只能是同个订单下的数据
	//orderDetailBos, err := service.OrdersDetailService.GetByIdListApi(l.ctx, req.IdList)
	//if err != nil || len(orderDetailBos) == 0 {
	//	return "", errors.New("传递订单详情id错误")
	//}
	//orderIdList := k.Map(orderDetailBos, func(item *bo.OrderDetailBo, index int) int64 {
	//	return item.OrdersID
	//})
	//orderIdList1 := k.Distinct(orderIdList)
	//if len(orderIdList1) > 1 {
	//	return "", errors.New("批量出库只能是同个订单下的商品")
	//}
	//orderId := orderIdList1[0]
	ordersEntity, err := service.OrdersService.GetByIdApi(l.ctx, req.OrdersID)
	if errors.Is(err, gorm.ErrRecordNotFound) {
		l.Logger.Infof("传递的订单号错误")
		return "", errors.New("传递的订单号错误")
	}
	// 判断当前订单是否有已经出库的
	var sendGoodsRecordID int64
	sendGoodsRecordEntity, err := service.SendGoodsRecordService.GetStoreSortingByOrderIdApi(l.ctx, req.OrdersID)
	// 创建出库数据
	tx := dao.Use(l.svcCtx.MysqlDb).Begin()
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// 第一次出库
		var sendGoodsRecordData = model.SendGoodsRecordEntity{
			OrderNo:      utils.GenerateTodayOrderNo(l.svcCtx.RedisDb, "FJCK"), // 订单流水号
			EnterpriseID: accountInfo.EnterpriseId,                             // 关联到enterprise表主键id
			CustomerID:   ordersEntity.CustomerID,                              // 客户id,关联到enterprise_customer表主键id
			TotalAmount:  ordersEntity.TotalAmount,                             // 订单金额
			TotalCount:   ordersEntity.TotalCount,                              // 订单商品数量
			WarehouseID:  ordersEntity.WarehouseID,                             // 发货单号,关联到warehouse表主键id
			OrdersID:     ordersEntity.ID,                                      // 关联到订单表id,orders表主键id
			OperateName:  accountInfo.PersonName,                               // 制单员
			OperateID:    accountInfo.PersonId,                                 // 制单员id,关联到员工表
		}
		if err = service.SendGoodsRecordService.CreateApi(l.ctx, tx, &sendGoodsRecordData); err != nil {
			if err = tx.Rollback(); err != nil {
				return "", err
			}
			return "", errors.New("创建失败")
		}
		sendGoodsRecordID = sendGoodsRecordData.ID
	} else {
		// 商品第二次出库
		sendGoodsRecordID = sendGoodsRecordEntity.ID
	}
	var sendGoodsRecordDetailDataList = make([]*model.SendGoodsRecordDetailEntity, 0)

	spuMap, err := service.OrdersDetailService.GetTotalSpuApi(l.ctx, []int64{req.OrdersID})
	if err != nil {
		return "", err
	}
	// 是orders_detail表的主键id
	for _, item := range req.SpuList {
		//ordersDetailEntity, err := service.OrdersDetailService.GetByIdApi(l.ctx, item)
		//if errors.Is(err, gorm.ErrRecordNotFound) {
		//	l.Logger.Infof("传递的订单号错误")
		//	if err = tx.Rollback(); err != nil {
		//		return "", err
		//	}
		//	return "", errors.New("传递的订单号错误")
		//}
		//l.Logger.Infof("当前订单详情信息:%+v", ordersDetailEntity)

		spu, err := service.SpuService.GetBySpuIdApi(l.ctx, item)

		// 根据订单查询分拣单信息
		storeSortingDetailEntity, err := service.StoreSortingDetailService.GetStoreSortingDetailBySpuIDApi(l.ctx, req.OrdersID, item)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			if err = tx.Rollback(); err != nil {
				return "", err
			}
			l.Logger.Infof("传递的订单id包括了未分拣出库的单,请重新选择")
			return "", errors.New("传递的订单id包括了未分拣出库的单,请重新选择")
		}

		outboundCount := decimal.New(0, 00)
		for _, v := range storeSortingDetailEntity {
			outboundCount = outboundCount.Add(v.OutboundCount)
		}

		unitName, _ := service.SpuService.GetUnitNameBySpuIdApi(l.ctx, spu.ID)
		// 创建明细
		var sendGoodsRecordDetailData = &model.SendGoodsRecordDetailEntity{
			SendGoodsRecordID:       sendGoodsRecordID,                       // 分拣单store_sorting主键id
			SpuID:                   spu.ID,                                  // 商品,关联到spu表主键id
			SnapshotSpuName:         spu.Name,                                // 快照商品名称
			SnapshotProductImageURL: spu.ProductImageURL,                     // 快照产品图片
			SnapshotSpuType:         spu.SpuType,                             // 快照商品类型,0表示基础商品,1表示加工商品
			SnapshotUnit:            unitName,                                // 快照单位
			SnapshotCategoryID:      spu.CategoryID,                          // 快照分类id
			SnapshotCategory:        spu.CategoryName,                        // 快照分类
			LossRate:                spu.LossRate,                            // 快照损耗率
			OrdersCount:             spuMap[item].Count,                      // 下单数量
			SnapshotPrice:           spu.SalesPrice,                          // 商品单价
			OutboundCount:           outboundCount,                           // 出库数量
			OperateName:             storeSortingDetailEntity[0].OperateName, // 出库员
			OperateID:               storeSortingDetailEntity[0].OperateID,   // 出库员id,关联到员工表
			Remark:                  storeSortingDetailEntity[0].Remark,      // 备注
		}
		sendGoodsRecordDetailDataList = append(sendGoodsRecordDetailDataList, sendGoodsRecordDetailData)
		//changeCount := storeSortingDetailEntity.OutboundCount.Add(storeSortingDetailEntity.LossCount)
		//// 扣减库存
		//if err = service.SpuInventoryService.ReduceInventoryApi(l.ctx, tx, accountInfo.EnterpriseId, ordersEntity.WarehouseID, ordersDetailEntity.SpuID, changeCount); err != nil {
		//	l.Logger.Infof("扣减库存失败:%v", err)
		//	if err1 := tx.Rollback(); err1 != nil {
		//		return "", err1
		//	}
		//	return "", err
		//}
		//// 库存记录
		//if err = service.InventRecordService.CreateInventRecordApi(l.ctx, tx, &model.InventoryRecordEntity{
		//	EnterpriseID: accountInfo.EnterpriseId,                          // 关联到enterprise表主键id
		//	SpuID:        ordersDetailEntity.SpuID,                          // 商品主键,关联到spu表主键id
		//	Types:        1,                                                 // 类型,0表示入库,1表示出库
		//	Source:       0,                                                 // 来源,0表示正常出入口,10表示盘点报损报溢,20表调拨
		//	WarehouseID:  ordersEntity.WarehouseID,                          // 仓库id,关联到warehouse表主键id
		//	ChangeCount:  changeCount,                                       // 变动数量
		//	Price:        ordersDetailEntity.SnapshotPrice,                  // 单价
		//	Amount:       changeCount.Mul(ordersDetailEntity.SnapshotPrice), // 金额
		//}); err != nil {
		//	if err = tx.Rollback(); err != nil {
		//		return "", err
		//	}
		//	return "", errors.New("操作失败")
		//}
	}
	if err = service.SendGoodsRecordDetailService.CreateBatchApi(l.ctx, tx, sendGoodsRecordDetailDataList); err != nil {
		if err = tx.Rollback(); err != nil {
			return "", err
		}
		return "", errors.New("操作失败")
	}
	if err = tx.Commit(); err != nil {
		l.Logger.Infof("事务提交失败:%+v", err)
		return "", errors.New("操作失败")
	}
	return "操作成功", nil
}
